﻿using System;
using System.Xml.Linq;

namespace WolframAlphaSharp
{
    public static class XElementExtensions
    {
        public static bool ParseAttributeAsBool(this XElement element, string name)
        {
            var attribute = GetAttribute(element, name);
            bool result;
            if (!bool.TryParse(attribute.Value, out result))
            {
                throw new ArgumentException(string.Format("Couldn't parse attribute '{0}' value of '{1}' into a boolean.", name, attribute.Value), "name");                
            }
            return result;
        }

        public static bool ParseAttributeAsBool(this XElement element, string name, bool defaultValue)
        {
            var attribute = element.Attribute(name);
            if (attribute != null)
            {
                bool result;
                if (bool.TryParse(attribute.Value, out result)) return result;
            }
            
            return defaultValue;
        }
        
        public static XAttribute GetAttribute(this XElement element, string name)
        {
            var attribute = element.Attribute(name);
            if (attribute == null) throw new ArgumentException(string.Format("Couldn't find attribute named '{0}' on element '{1}'", name, element), "name");
            return attribute;
        }

        public static int ParseAttributeAsInt(this XElement element, string name)
        {
            var attribute = GetAttribute(element, name);
            int result;
            if (!int.TryParse(attribute.Value, out result))
            {
                throw new ArgumentException(string.Format("Couldn't parse attribute '{0}' value of '{1}' into an integer.", name, attribute.Value), "name");
            }
            return result;
        }

        public static double ParseAttributeAsDouble(this XElement element, string name)
        {
            var attribute = GetAttribute(element, name);
            double result;
            if (!double.TryParse(attribute.Value, out result))
            {
                throw new ArgumentException(string.Format("Couldn't parse attribute '{0}' value of '{1}' into a double.", name, attribute.Value), "name");
            }
            return result;
        }

        public static Uri ParseAttributeAsUri(this XElement element, string name)
        {
            var attribute = GetAttribute(element, name);
            Uri result;
            if (!Uri.TryCreate(attribute.Value, UriKind.Absolute, out result))
            {
                throw new ArgumentException(string.Format("Couldn't parse attribute '{0}' value of '{1}' into a Uri.", name, attribute.Value), "name");
            }
            return result;
        }

        public static Version ParseAttributeAsVersion(this XElement element, string name)
        {
            var attribute = GetAttribute(element, name);
            
            try
            {
                return new Version(attribute.Value);
            }
            catch (Exception ex)
            {
                throw new ArgumentException(
                    string.Format("Couldn't parse attribute '{0}' value of '{1}' into a Version.", name, attribute.Value), ex);
            }
        }
    }
}